﻿using FluentAssertions;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using NewRetail.Application.Components.Goods.Entity;
using NewRetail.Application.Components.Platform;
using NewRetail.Application.Components.Platform.Entity;
using NewRetail.Application.Components.Platform.Model;
using NewRetail.Application.Core;
using Serilog;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Domain.Repositories;

namespace NewRetail.Api.Controllers
{
    [NewRetailRoute("pos-sales-flow")]
    public class PosSalesFlowController : BaseController<PosSalesFlow, PosSalesFlowFilterDto>
    {
        private readonly IPosSalesFlowService posSalesFlowService;
        public PosSalesFlowController(
            IPosSalesFlowService posSalesFlowService)
        {
            this.posSalesFlowService = posSalesFlowService;
        }

        protected override async Task<IQueryable<PosSalesFlow>> FilterQueryPaging(DbContext db, IQueryable<PosSalesFlow> query, PosSalesFlowFilterDto dto)
        {
            if (!string.IsNullOrWhiteSpace(dto.warehouseId))
            {
                query = query.Where(x => x.warehouseID == dto.warehouseId);
            }
            if (!string.IsNullOrWhiteSpace(dto.goodsId))
            {
                query = query.Where(x => x.goodsID == dto.goodsId);
            }
            if (!string.IsNullOrWhiteSpace(dto.cashierId))
            {
                query = query.Where(x => x.cashierID == dto.cashierId);
            }
            if (!string.IsNullOrWhiteSpace(dto.flowNo))
            {
                query = query.Where(x => x.flowNo.Contains(dto.flowNo));
            }
            if (!string.IsNullOrWhiteSpace(dto.goodsName))
            {
                var goodsIds = db.Set<GoodsInfo>().AsNoTracking()
                    .Where(x => x.goodsName.Contains(dto.goodsName)).Select(x => x.Id);

                query = query.Where(x => goodsIds.Contains(x.goodsID));
            }
            if (!string.IsNullOrWhiteSpace(dto.No))
            {
                var goodsIds = db.Set<GoodsInfo>().AsNoTracking()
                    .Where(x => x.No.Contains(dto.No)).Select(x => x.Id);

                query = query.Where(x => goodsIds.Contains(x.goodsID));
            }

            if (!string.IsNullOrWhiteSpace(dto.cashierName))
            {
                var cashierIds = db.Set<PosCashier>().AsNoTracking()
                    .Where(x => x.cashierName.Contains(dto.cashierName)).Select(x => x.Id);

                query = query.Where(x => cashierIds.Contains(x.cashierID));
            }

            if (dto.startTime != null)
            {
                query = query.Where(x => x.operateTime >= dto.startTime.Value);
            }
            if (dto.endTime != null)
            {
                query = query.Where(x => x.operateTime < dto.endTime.Value);
            }
            if (dto.startSalePrice != null)
            {
                query = query.Where(x => x.salePrice >= dto.startSalePrice);
            }
            if (dto.endSalePrice != null)
            {
                query = query.Where(x => x.salePrice <= dto.endSalePrice);
            }
            //类别条件 add 20230111
            if (!string.IsNullOrWhiteSpace(dto.categoryID))
            {
                query = query.Where(x => x.categoryID == dto.categoryID);
            }
            if (!string.IsNullOrWhiteSpace(dto.categoryName))
            {
                var categoryIds = db.Set<GoodsCategory>().AsNoTracking()
                    .Where(x => x.categoryName.Contains(dto.categoryName)).Select(x => x.Id);

                query = query.Where(x => categoryIds.Contains(x.categoryID));
            }
            if (!string.IsNullOrWhiteSpace(dto.categoryNo))
            {
                var categoryIds = db.Set<GoodsCategory>().AsNoTracking()
                    .Where(x => x.No.Contains(dto.categoryNo)).Select(x => x.Id);

                query = query.Where(x => categoryIds.Contains(x.categoryID));
            }
            //过滤会员
            if (!string.IsNullOrWhiteSpace(dto.memberCardOrTel))
            {
                //根据入参获取会员id
                var posMembers = await this.posSalesFlowService.GetPosMemberInfosByCardOrTel(dto.memberCardOrTel);
                if (posMembers != null)
                {
                    var memberIds = posMembers.Select(x => x.Id);
                    query = query.Where(x => memberIds.Contains(x.memberID));
                }
            }

            return await base.FilterQueryPaging(db, query, dto);
        }

        protected override async Task<IQueryable<PosSalesFlow>> OrderQueryPaging(IQueryable<PosSalesFlow> query, PosSalesFlowFilterDto dto)
        {
            await Task.CompletedTask;

            query = query.OrderByDescending(x => x.addTime).ThenByDescending(x => x.operateTime);
            return query;
        }

        public override async Task<ResponseEntity<PagedResultDto<PosSalesFlow>>> QueryPaging([FromBody] PosSalesFlowFilterDto dto)
        {
            var res = await base.QueryPaging(dto);

            if (res.Data?.Items?.Any() ?? false)
            {
                res.Data.Items = await this.posSalesFlowService.AttachWarehouse(res.Data.Items.ToArray());
                res.Data.Items = await this.posSalesFlowService.AttachGoodsInfo(res.Data.Items.ToArray());
                res.Data.Items = await this.posSalesFlowService.AttachGoodsCategory(res.Data.Items.ToArray());
                res.Data.Items = await this.posSalesFlowService.AttachCashier(res.Data.Items.ToArray());
                res.Data.Items = await this.posSalesFlowService.AttachCashRegister(res.Data.Items.ToArray());
                res.Data.Items = await this.posSalesFlowService.AttachMember(res.Data.Items.ToArray());
                res.Data.Items = await this.posSalesFlowService.AttachSupplier(res.Data.Items.ToArray());
            }

            return res;
        }

        #region add by cl 20221114

        #region 销售按商品汇总统计
        [HttpPost("query-possalesummarystatisticsgood")]
        public async Task<ResponseEntity<PagedResultDto<PosSaleSummaryStatisticsGoodShowDto>>> QueryPosSaleSummaryStatisticsGood([FromBody] QueryPosSaleSummaryStatisticsGoodInputDto inputDto)
        {
            var ret = new ResponseEntity<PagedResultDto<PosSaleSummaryStatisticsGoodShowDto>>();
            try
            {
                var result = await this.posSalesFlowService.GetPosSaleSummaryStatisticsGoodInfo(inputDto);
                ret.SetData(result);
            }
            catch (Exception e)
            {
                ret.SetError("失败！" + e.Message);
            }

            return ret;
        }
        #endregion

        #region 类别商品销售统计。针对门店的所有类别的销售统计
        [HttpPost("query-possalecategorysummarystatisticsgood")]
        public async Task<ResponseEntity<IEnumerable<PosSaleCategorySummaryStatisticsGoodShowDto>>> QueryPosSaleCategorySummaryStatisticsGood([FromBody] QueryPosSaleSummaryStatisticsGoodDto inputDto)
        {
            var ret = new ResponseEntity<IEnumerable<PosSaleCategorySummaryStatisticsGoodShowDto>>();
            try
            {
                var result = await this.posSalesFlowService.GetPosSaleCategorySummaryStatisticsGoodInfo(inputDto);
                ret.SetData(result);
            }
            catch (Exception e)
            {
                ret.SetError("失败！" + e.Message);
            }

            return ret;
        }
        #endregion

        #region 类别商品销售统计。针对收银员的所有类别的销售统计
        [HttpPost("query-possalecashiercategorysummarystatisticsgood")]
        public async Task<ResponseEntity<IEnumerable<PosSaleCashierCategorySummaryStatisticsGoodShowDto>>> QueryPosSaleCashierCategorySummaryStatisticsGood([FromBody] QueryPosSaleSummaryStatisticsGoodDto inputDto)
        {
            var ret = new ResponseEntity<IEnumerable<PosSaleCashierCategorySummaryStatisticsGoodShowDto>>();
            try
            {
                var result = await this.posSalesFlowService.GetPosSaleCashierCategorySummaryStatisticsGoodInfo(inputDto);
                ret.SetData(result);
            }
            catch (Exception e)
            {
                ret.SetError("失败！" + e.Message);
            }

            return ret;
        }
        #endregion

        #endregion

        #region add by cl 20240506
        [HttpPost("export-possalesflow-query-paging")]
        public async Task<IActionResult> ExportPosSalesFlowQueryPaging([FromBody] PosSalesFlowFilterDto dto)
        {
            try
            {
                var res = await QueryPaging(dto);

                if (res.Data?.Items?.Any() ?? false)
                {
                    var result = this.posSalesFlowService.ExportPosSalesFlowsInfo(res.Data.Items.ToArray());
                    var fName = string.Concat("销售流水信息");
                    if (result != null)
                        return File(result, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", $"{DateTime.Now.ToString("yyyyMMddHHmmss")}_{fName}.xlsx");
                }
            }
            catch (Exception e)
            {
                Log.Error(e.Message);
            }
            return BadRequest("销售流水信息导出失败！");
        }
        #endregion

        #region 根据销售流水号和日期查找订单,供POS端按订单退货时候查找订单使用
        [HttpPost("get-possaleflows-byflowno")]
        public async Task<ResponseEntity<PosSalesFlow[]>> GetPosSaleFlowss([FromBody] PosSalesFlowFilterDto dto)
        {
            dto.Should().NotBeNull();
            dto.flowNo.Should().NotBeNullOrEmpty();
            dto.startTime.Should().NotBeNull();
            dto.endTime.Should().NotBeNull();
            var db = await this.Repo.GetDbContextAsync();

            var query = from map in db.Set<PosSalesFlow>().IgnoreQueryFilters().AsNoTracking().Where(x => x.operateTime >= dto.startTime && x.operateTime <= dto.endTime && x.flowNo.Contains(dto.flowNo))
                        join goods in db.Set<GoodsInfo>().IgnoreQueryFilters().AsNoTracking() on map.goodsID equals goods.Id into os
                        from good in os.DefaultIfEmpty()
                            //join sysDics in db.Set<SysDicsEntity>().IgnoreQueryFilters().AsNoTracking() on good.unit equals sysDics.ID into sd
                        select new { map, good };

            var data = await query.ToArrayAsync();

            var res = data.Select(x =>
            {
                x.map.GoodsInfo = x.good;
                return x.map;
            }).ToArray();

            return new ResponseEntity<PosSalesFlow[]>().SetData(res);
        }
        #endregion
    }
}
